package com.qf.shrio2203.config;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.shrio2203.untils.ApplicationContextUtils;
import com.qf.shrio2203.user.entity.*;
import com.qf.shrio2203.user.service.*;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class CustomRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;
    @Autowired
    UserRoleService userRoleService;
    @Autowired
    RoleService roleService;
    @Autowired
    RolePermsService rolePermsService;
    @Autowired
    PersService persService;



    /**
     * 通过这个方法 向shiro提供当前用户的权限相关信息
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        //获取用户的身份信息
        User user = (User) principals.getPrimaryPrincipal();
        List<String> roles = user.getRoles();
        List<String> perms = user.getPerms();
        //把信息封装到AuthorizationInfo中   simpleAuthorizationInfo时AuthorizationInfo实现类
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //添加角色信息
        //添加一个
        // simpleAuthorizationInfo.addRole("admin");
        //simpleAuthorizationInfo.addRoles(roles);
        //添加权限信息
        // simpleAuthorizationInfo.addStringPermission("order:get");
        simpleAuthorizationInfo.addStringPermissions(perms);

        return simpleAuthorizationInfo;
    }

    /**
     * 查权限
     *
     * @param user
     * @return
     */
    public List<String> getPermsFromDB(User user) {
        //根据用户id查角色id
        LambdaQueryWrapper<UserRole> URWapper = new LambdaQueryWrapper<UserRole>()
                .select(UserRole::getRoleid)
                .eq(UserRole::getUserid, user.getId());
        List<Object> roleIdList = userRoleService.listObjs(URWapper);
        //查询roleperm
        QueryWrapper<RolePerms> RPWapper = new QueryWrapper<>();
        RPWapper.select("permsid").in("roleid", roleIdList);
        List<Object> permIdList = rolePermsService.listObjs(RPWapper);
        //查tpers
        QueryWrapper<Pers> PWapper = new QueryWrapper<>();
        PWapper.select("name").in("id", permIdList);
        List<Object> permName = persService.listObjs(PWapper);
        //集合类型转换 List<Object>->List<String>
        ArrayList<String> perNameStringList = new ArrayList<>();
        for (Object o : permName) {
            perNameStringList.add(o.toString());
        }
        return perNameStringList;
    }

    /**
     * 查角色
     *
     * @param user
     * @return
     */
    public List<String> getRolesFromDB(User user) {
        //根据用户id查角色id
        LambdaQueryWrapper<UserRole> URWapper = new LambdaQueryWrapper<UserRole>()
                .select(UserRole::getRoleid)
                .eq(UserRole::getUserid, user.getId());
        List<Object> roleIdList = userRoleService.listObjs(URWapper);
        //根据角色id查角色名字
        LambdaQueryWrapper<Role> RWapper = new LambdaQueryWrapper<Role>()
                .select(Role::getName)
                .in(Role::getId, roleIdList);
        List<Object> RloeName = roleService.listObjs(RWapper);
        //集合类型转换 List<Object>->List<String>
        List<String> roleNameStringList = RloeName.stream()//转换stream流对象
                .map(obj -> obj.toString())  //把集合的数据类型转换
                .collect(Collectors.toList()); //把stream对象转换list

        return roleNameStringList;
    }

    /**
     * 通过这个方法 向shrio提供 当前用户的身份印证信息
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println(token);
        //获取用户名
        String username = (String) token.getPrincipal();
        //根据token中用户提供的身份信息，去数据库查密码
        User user = getUserFromDB(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        List<String> rolesFromDB = getRolesFromDB(user);
        List<String> perms = getPermsFromDB(user);
        user.setRoles(rolesFromDB);
        user.setPerms(perms);
        //把数据库密码返回shiro(第一个参数可以放user 或字符串，是object类型) //影响后续从shiro中取出对象的类型
        //第二个参数放入数据库中查询的密码
        //第三个是当前提供身份信息的realm名字
        SimpleAuthenticationInfo simpleAuthenticationInfo =
                new SimpleAuthenticationInfo(user, user.getPassword(),
                        ByteSource.Util.bytes(user.getSalt()),//把当前用户的盐给shiro
                        this.getName());
        return simpleAuthenticationInfo;
    }

    /**
     * 根据用户名获取用户
     *
     * @param username
     * @return
     */
    private User getUserFromDB(String username) {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", username);
        User user = userService.getOne(userQueryWrapper);

//        User one = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));

        return user;
    }
}


